#include "FRThreadPool.h"

FRThreadPool::FRThreadPool(const int16_t c_poolSize)
    : m_isStart(false), m_aPoolSize(c_poolSize), m_aActiveSize(0)
{
    // 若传递参数小于等于0则取当前硬件支持最大并行线程数
    if (c_poolSize <= 0)
    {
        m_aPoolSize.store(std::thread::hardware_concurrency(), std::memory_order_release);
    }
}

FRThreadPool::~FRThreadPool()
{
    Stop();
}

void FRThreadPool::Start()
{
    // 线程池中最大线程数
    int16_t maxThread = 0;

    // 线程池停止状态则可以开始添加线程，并置为启动状态
    if (!m_isStart.exchange(true, std::memory_order_acquire))
    {
        // 活跃线程数置为0
        m_aActiveSize.store(0, std::memory_order_release);
        // 获取线程池中的线程数
        maxThread = m_aPoolSize.load(std::memory_order_acquire);
        // 清空线程池中的线程
        m_vecThreads.clear();

        // 向线程池中添加线程
        for (int16_t i = 0; i < maxThread; i++)
        {
            m_vecThreads.push_back(std::thread([this] {
                // 当线程池存在时，每条线程持续该循环
                while (m_isStart.load(std::memory_order_acquire))
                {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> uLock(this->m_mtx);

                        // 若该线程池停止或者任务队列不为空则停止等待
                        this->m_cv.wait(uLock, [this] {
                            return !this->m_isStart.load(std::memory_order_acquire) || !this->m_queTask.empty();
                        });

                        // 若线程池停止则立马退出该线程循环
                        if (!this->m_isStart.load(std::memory_order_acquire))
                        {
                            return;
                        }

                        // 将任务队列中的第一个任务取出
                        task = std::move(this->m_queTask.front());
                        this->m_queTask.pop();
                    }
                    // 执行任务，记录活跃线程数
                    this->m_aActiveSize.fetch_add(1, std::memory_order_release);
                    task();
                    this->m_aActiveSize.fetch_sub(1, std::memory_order_release);
                }
            }));
        }
    }
    else
    {
        throw std::runtime_error("The thread pool has started");
    }
}

void FRThreadPool::Stop()
{
    // 当线程池启动时则停止所有线程，并将线程池置为停止
    if (m_isStart.exchange(false, std::memory_order_acquire))
    {
        // 唤醒所有线程，使所有线程退出等待状态
        m_cv.notify_all();

        // 将线程池内所有线程汇入主线程
        std::for_each(m_vecThreads.begin(), m_vecThreads.end(), [](std::thread &t) {
            if (t.joinable())
            {
                t.join();
            }
        });
    }
}

int16_t FRThreadPool::GetPoolSize() const
{
    return m_aPoolSize.load(std::memory_order_acquire);
}

void FRThreadPool::ResizePool(const int16_t c_size)
{
    // 当该线程池停止时则可以调节线程池大小，否则抛出异常
    if (!m_isStart.load(std::memory_order_acquire))
    {
        if (c_size <= 0)
        {
            m_aPoolSize.store(std::thread::hardware_concurrency(), std::memory_order_release);
        }
        else
        {
            m_aPoolSize.store(c_size, std::memory_order_release);
        }
    }
    else
    {
        throw std::runtime_error("Disallow modifying thread pool");
    }
}

int16_t FRThreadPool::GetActiveSize() const
{
    return m_aActiveSize.load(std::memory_order_acquire);
}

size_t FRThreadPool::GetDequeSize()
{
    std::unique_lock<std::mutex> uLock(m_mtx);

    return m_queTask.size();
}

bool FRThreadPool::IsStarted() const
{
    return m_isStart.load(std::memory_order_acquire);
}
